﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.Threading;

namespace wificonf
{
    class Program
    {
        static int Main (string [] args)
        {
            if (args.Length != 4)
            {
                usage();
                Console.WriteLine("Presione una tecla para continuar");
                return -1;
            }

            bool parar = bool.Parse(args[3]);
            string s = string.Empty;
            SerialPort sp = new SerialPort(
                args[0], int.Parse(args[1])
            );
            sp.Handshake = (Handshake) int.Parse(args[2]); 
            sp.Open();

            try
            {
                // WLAN
                Thread.Sleep(250);
                ejecutar(sp, "$$$", 3, 1000, "$$$", "CMD");
                ejecutar(sp, "set wlan join 0[CR][LF]", 3, 800, "AOK");
                ejecutar(sp, "set wlan ssid Rosario$Bus[CR][LF]", 3, 800, "AOK");
                ejecutar(sp, "set wlan passphrase WiFi-coches-RBUS.117[CR][LF]", 3, 800, "AOK");
                ejecutar(sp, "save[CR][LF]", 3, 1000, "Storing in config");
                ejecutar(sp, "reboot[CR][LF]", 3, 1500, "*READY*");

                // SYS
                Thread.Sleep(250);
                ejecutar(sp, "$$$", 3, 1000, "$$$", "CMD");
                ejecutar(sp, "set sys printlvl 0x4001[CR][LF]", 3, 800, "AOK");
                ejecutar(sp, "save[CR][LF]", 3, 1000, "Storing in config");
                ejecutar(sp, "reboot[CR][LF]", 3, 1500, "*READY*");

                // FTP
                Thread.Sleep(250);
                ejecutar(sp, "$$$", 3, 1000, "$$$", "CMD");
                ejecutar(sp, "set ftp user anonymous[CR][LF]", 3, 800, "AOK");
                ejecutar(sp, "set ftp pass 0[CR][LF]", 3, 800, "AOK");
                ejecutar(sp, "save[CR][LF]", 3, 1000, "Storing in config");
                ejecutar(sp, "reboot[CR][LF]", 3, 1500, "*READY*");

                // COMM
                Thread.Sleep(250);
                ejecutar(sp, "$$$", 3, 1000, "$$$", "CMD");
                ejecutar(sp, "set comm remote 0[CR][LF]", 3, 800, "AOK");
                ejecutar(sp, "save[CR][LF]", 3, 1000, "Storing in config");
                ejecutar(sp, "reboot[CR][LF]", 3, 1500, "*READY*");

                // IP
                Thread.Sleep(250);
                ejecutar(sp, "$$$", 3, 1000, "$$$", "CMD");
                ejecutar(sp, "set ip dhcp 1[CR][LF]", 3, 800, "AOK");
                ejecutar(sp, "save[CR][LF]", 3, 1000, "Storing in config");
                ejecutar(sp, "reboot[CR][LF]", 3, 1500, "*READY*");

                // UART
                Thread.Sleep(250);
                ejecutar(sp, "$$$", 3, 1000, "$$$", "CMD");
                ejecutar(sp, "set uart baudrate 115200[CR][LF]", 3, 800, "AOK");
                ejecutar(sp, "set uart flow 1[CR][LF]", 3, 800, "AOK");
                ejecutar(sp, "save[CR][LF]", 3, 1000, "Storing in config");
                ejecutar(sp, "reboot[CR][LF]", 3, 1000, "*Reboot*");

                Console.WriteLine();
                Console.WriteLine(">>>>>>>>>>>>>>>>>>>> FIN >>>>>>>>>>>>>>>>>>>>");
                sp.Close();
                if (parar)
                    Console.ReadLine();
                return 0;
            }
            catch (Exception exx)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(exx.Message);
                if (parar)
                    Console.ReadLine();
                return -2;
            }
        }

        private static void usage()
        {
            Console.WriteLine("Uso wificonf PUERTO BAUDRATE HANDSHAKE PARAR_AL_FINAL");
            Console.WriteLine("     ej de PUERTO          COM1");
            Console.WriteLine("     ej de BAUDRATE        9600");
            Console.WriteLine("     ej de HANDSHAKE       2");
            Console.WriteLine("     (0=None, 1=XonXoff, 2=Hardware)");
            Console.WriteLine("     ej de PARAR           true");
            Console.WriteLine("     (para o no para la ejecucion al finalizar)");
            Console.WriteLine();
            Console.WriteLine("Ejemplo final:");
            Console.WriteLine("     wificonf COM1 9600 2 false");
            Console.WriteLine();
            Console.WriteLine("Cualquier cosa hablar con ale! :D hav29a@gmail.com");
            Console.WriteLine();
        }

        static bool ejecutar (SerialPort sp, string representacionComando, int veces, int espera, params string[] respEsperadas)
        {
            string comando = representacionComando
                .Replace("[CR]", "\r")
                .Replace("[LF]", "\n")
            ;
            
            for (int i = 0; i < veces; i++)
            {
                Console.ForegroundColor = ConsoleColor.Gray;
                Console.WriteLine("ejecutando {0}", representacionComando);
                sp.Write(comando);
                Console.WriteLine("esperando {0} milis", espera);
                Thread.Sleep(espera);
                string resp = sp.ReadExisting();
                Console.ForegroundColor = ConsoleColor.DarkGreen;
                Console.WriteLine("respuesta:\r\n{0}", resp);
                if (respEsperadas.Length == 0) {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("\tok!");
                    return true;
                }
                foreach (string respEsperada in respEsperadas)
                    if (resp.Contains(respEsperada)) {
                        Console.ForegroundColor = ConsoleColor.Green;
                        Console.WriteLine("\tok!");
                        return true;
                    }
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("\tninguna respuesta coincidio...");
            }

            throw new Exception(string.Format(
                "no se pudo procesar el comando: {0}", 
                representacionComando
            ));
        }
    }
}
